<!DOCTYPE html>

<html>
<head>
  <title>filters.coffee</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page">
            
              
              <a class="source" href="analyze.html">
                analyze.coffee
              </a>
            
              
              <a class="source" href="autoload.html">
                autoload.coffee
              </a>
            
              
              <a class="source" href="blender.html">
                blender.coffee
              </a>
            
              
              <a class="source" href="calculate.html">
                calculate.coffee
              </a>
            
              
              <a class="source" href="caman.html">
                caman.coffee
              </a>
            
              
              <a class="source" href="convert.html">
                convert.coffee
              </a>
            
              
              <a class="source" href="event.html">
                event.coffee
              </a>
            
              
              <a class="source" href="filter.html">
                filter.coffee
              </a>
            
              
              <a class="source" href="io.html">
                io.coffee
              </a>
            
              
              <a class="source" href="layer.html">
                layer.coffee
              </a>
            
              
              <a class="source" href="logger.html">
                logger.coffee
              </a>
            
              
              <a class="source" href="module.html">
                module.coffee
              </a>
            
              
              <a class="source" href="pixel.html">
                pixel.coffee
              </a>
            
              
              <a class="source" href="plugin.html">
                plugin.coffee
              </a>
            
              
              <a class="source" href="renderer.html">
                renderer.coffee
              </a>
            
              
              <a class="source" href="store.html">
                store.coffee
              </a>
            
              
              <a class="source" href="util.html">
                util.coffee
              </a>
            
              
              <a class="source" href="blenders.html">
                blenders.coffee
              </a>
            
              
              <a class="source" href="filters.html">
                filters.coffee
              </a>
            
              
              <a class="source" href="size.html">
                size.coffee
              </a>
            
              
              <a class="source" href="blur.html">
                blur.coffee
              </a>
            
              
              <a class="source" href="camera.html">
                camera.coffee
              </a>
            
              
              <a class="source" href="compoundBlur.html">
                compoundBlur.coffee
              </a>
            
              
              <a class="source" href="edges.html">
                edges.coffee
              </a>
            
              
              <a class="source" href="posterize.html">
                posterize.coffee
              </a>
            
              
              <a class="source" href="presets.html">
                presets.coffee
              </a>
            
              
              <a class="source" href="rotate.html">
                rotate.coffee
              </a>
            
              
              <a class="source" href="stackBlur.html">
                stackBlur.coffee
              </a>
            
              
              <a class="source" href="threshold.html">
                threshold.coffee
              </a>
            
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>filters.coffee</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              <p>The filters define all of the built-in functionality that comes with Caman (as opposed to being 
provided by a plugin). All of these filters are ratherbasic, but are extremely powerful when
many are combined. For information on creating plugins, check out the 
<a href="http://camanjs.com/docs/plugin-creation">Plugin Creation</a> page, and for information on using 
the plugins, check out the <a href="http://camanjs.com/docs/built-in">Built-In Functionality</a> page.</p>
<h2>Fill Color</h2>
<p>Fills the canvas with a single solid color.</p>
<h3>Arguments</h3>
<p>Can take either separate R, G, and B values as arguments, or a single hex color value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"fillColor"</span>, -&gt;
  <span class="keyword">if</span> arguments.length <span class="keyword">is</span> <span class="number">1</span>
    color = Convert.hexToRGB arguments[<span class="number">0</span>]
  <span class="keyword">else</span>
    color =
      r: arguments[<span class="number">0</span>]
      g: arguments[<span class="number">1</span>]
      b: arguments[<span class="number">2</span>]

  <span class="property">@process</span> <span class="string">"fillColor"</span>, (rgba) -&gt;
    rgba.r = color.r
    rgba.g = color.g
    rgba.b = color.b
    rgba.a = <span class="number">255</span>
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <h2>Brightness</h2>
<p>Simple brightness adjustment</p>
<h3>Arguments</h3>
<p>Range is -100 to 100. Values &lt; 0 will darken image while values &gt; 0 will brighten.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"brightness"</span>, (adjust) -&gt;
  adjust = Math.floor <span class="number">255</span> * (adjust / <span class="number">100</span>)

  <span class="property">@process</span> <span class="string">"brightness"</span>, (rgba) -&gt;
    rgba.r += adjust
    rgba.g += adjust
    rgba.b += adjust
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <h2>Saturation</h2>
<p>Adjusts the color saturation of the image.</p>
<h3>Arguments</h3>
<p>Range is -100 to 100. Values &lt; 0 will desaturate the image while values &gt; 0 will saturate it.
<strong>If you want to completely desaturate the image</strong>, using the greyscale filter is highly 
recommended because it will yield better results.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"saturation"</span>, (adjust) -&gt;
  adjust *= -<span class="number">0.01</span>

  <span class="property">@process</span> <span class="string">"saturation"</span>, (rgba) -&gt;
    max = Math.max rgba.r, rgba.g, rgba.b

    rgba.r += (max - rgba.r) * adjust <span class="keyword">if</span> rgba.r <span class="keyword">isnt</span> max
    rgba.g += (max - rgba.g) * adjust <span class="keyword">if</span> rgba.g <span class="keyword">isnt</span> max
    rgba.b += (max - rgba.b) * adjust <span class="keyword">if</span> rgba.b <span class="keyword">isnt</span> max
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <h2>Vibrance</h2>
<p>Similar to saturation, but adjusts the saturation levels in a slightly smarter, more subtle way. 
Vibrance will attempt to boost colors that are less saturated more and boost already saturated
colors less, while saturation boosts all colors by the same level.</p>
<h3>Arguments</h3>
<p>Range is -100 to 100. Values &lt; 0 will desaturate the image while values &gt; 0 will saturate it.
<strong>If you want to completely desaturate the image</strong>, using the greyscale filter is highly 
recommended because it will yield better results.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"vibrance"</span>, (adjust) -&gt;
  adjust *= -<span class="number">1</span>

  <span class="property">@process</span> <span class="string">"vibrance"</span>, (rgba) -&gt;
    max = Math.max rgba.r, rgba.g, rgba.b
    avg = (rgba.r + rgba.g + rgba.b) / <span class="number">3</span>
    amt = ((Math.abs(max - avg) * <span class="number">2</span> / <span class="number">255</span>) * adjust) / <span class="number">100</span>

    rgba.r += (max - rgba.r) * amt <span class="keyword">if</span> rgba.r <span class="keyword">isnt</span> max
    rgba.g += (max - rgba.g) * amt <span class="keyword">if</span> rgba.g <span class="keyword">isnt</span> max
    rgba.b += (max - rgba.b) * amt <span class="keyword">if</span> rgba.b <span class="keyword">isnt</span> max
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <h2>Greyscale</h2>
<p>An improved greyscale function that should make prettier results
than simply using the saturation filter to remove color. It does so by using factors
that directly relate to how the human eye perceves color and values. There are
no arguments, it simply makes the image greyscale with no in-between.</p>
<p>Algorithm adopted from <a href="http://www.phpied.com/image-fun/">http://www.phpied.com/image-fun/</a></p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"greyscale"</span>, (adjust) -&gt;
  <span class="property">@process</span> <span class="string">"greyscale"</span>, (rgba) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>Calculate the average value of the 3 color channels 
using the special factors</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    avg = Calculate.luminance(rgba)

    rgba.r = avg
    rgba.g = avg
    rgba.b = avg
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <h2>Contrast</h2>
<p>Increases or decreases the color contrast of the image.</p>
<h3>Arguments</h3>
<p>Range is -100 to 100. Values &lt; 0 will decrease contrast while values &gt; 0 will increase contrast.
The contrast adjustment values are a bit sensitive. While unrestricted, sane adjustment values 
are usually around 5-10.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"contrast"</span>, (adjust) -&gt;
  adjust = Math.pow((adjust + <span class="number">100</span>) / <span class="number">100</span>, <span class="number">2</span>)

  <span class="property">@process</span> <span class="string">"contrast"</span>, (rgba) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>Red channel</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rgba.r /= <span class="number">255</span>;
    rgba.r -= <span class="number">0.5</span>;
    rgba.r *= adjust;
    rgba.r += <span class="number">0.5</span>;
    rgba.r *= <span class="number">255</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>Green channel</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rgba.g /= <span class="number">255</span>;
    rgba.g -= <span class="number">0.5</span>;
    rgba.g *= adjust;
    rgba.g += <span class="number">0.5</span>;
    rgba.g *= <span class="number">255</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>Blue channel</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rgba.b /= <span class="number">255</span>;
    rgba.b -= <span class="number">0.5</span>;
    rgba.b *= adjust;
    rgba.b += <span class="number">0.5</span>;
    rgba.b *= <span class="number">255</span>;

    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <h2>Hue</h2>
<p>Adjusts the hue of the image. It can be used to shift the colors in an image in a uniform 
fashion. If you are unfamiliar with Hue, I recommend reading this 
<a href="http://en.wikipedia.org/wiki/Hue">Wikipedia article</a>.</p>
<h3>Arguments</h3>
<p>Range is 0 to 100
Sometimes, Hue is expressed in the range of 0 to 360. If that&#39;s the terminology you&#39;re used to, 
think of 0 to 100 representing the percentage of Hue shift in the 0 to 360 range.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"hue"</span>, (adjust) -&gt;
  <span class="property">@process</span> <span class="string">"hue"</span>, (rgba) -&gt;
    hsv = Convert.rgbToHSV rgba.r, rgba.g, rgba.b
    
    h = hsv.h * <span class="number">100</span>
    h += Math.abs adjust
    h = h % <span class="number">100</span>
    h /= <span class="number">100</span>
    hsv.h = h

    {r, g, b} = Convert.hsvToRGB hsv.h, hsv.s, hsv.v
    rgba.r = r; rgba.g = g; rgba.b = b
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <h2>Colorize</h2>
<p>Uniformly shifts the colors in an image towards the given color. The adjustment range is from 0 
to 100. The higher the value, the closer the colors in the image shift towards the given 
adjustment color.</p>
<h3>Arguments</h3>
<p>This filter is polymorphic and can take two different sets of arguments. Either a hex color 
string and an adjustment value, or RGB colors and an adjustment value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"colorize"</span>, -&gt;
  <span class="keyword">if</span> arguments.length <span class="keyword">is</span> <span class="number">2</span>
    rgb = Convert.hexToRGB(arguments[<span class="number">0</span>])
    level = arguments[<span class="number">1</span>]
  <span class="keyword">else</span> <span class="keyword">if</span> arguments.length <span class="keyword">is</span> <span class="number">4</span>
    rgb =
      r: arguments[<span class="number">0</span>]
      g: arguments[<span class="number">1</span>]
      b: arguments[<span class="number">2</span>]

    level = arguments[<span class="number">3</span>]

  <span class="property">@process</span> <span class="string">"colorize"</span>, (rgba) -&gt;
    rgba.r -= (rgba.r - rgb.r) * (level / <span class="number">100</span>)
    rgba.g -= (rgba.g - rgb.g) * (level / <span class="number">100</span>)
    rgba.b -= (rgba.b - rgb.b) * (level / <span class="number">100</span>)
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <h2>Invert</h2>
<p>Inverts all colors in the image by subtracting each color channel value from 255. No arguments.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"invert"</span>, -&gt;
  <span class="property">@process</span> <span class="string">"invert"</span>, (rgba) -&gt;
    rgba.r = <span class="number">255</span> - rgba.r
    rgba.g = <span class="number">255</span> - rgba.g
    rgba.b = <span class="number">255</span> - rgba.b
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              <h2>Sepia</h2>
<p>Applies an adjustable sepia filter to the image.</p>
<h3>Arguments</h3>
<p>Assumes adjustment is between 0 and 100, which represents how much the sepia filter is applied.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"sepia"</span>, (adjust = <span class="number">100</span>) -&gt;
  adjust /= <span class="number">100</span>

  <span class="property">@process</span> <span class="string">"sepia"</span>, (rgba) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>All three color channels have special conversion factors that 
define what sepia is. Here we adjust each channel individually, 
with the twist that you can partially apply the sepia filter.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rgba.r = Math.min(<span class="number">255</span>, (rgba.r * (<span class="number">1</span> - (<span class="number">0.607</span> * adjust))) + (rgba.g * (<span class="number">0.769</span> * adjust)) + (rgba.b * (<span class="number">0.189</span> * adjust)));
    rgba.g = Math.min(<span class="number">255</span>, (rgba.r * (<span class="number">0.349</span> * adjust)) + (rgba.g * (<span class="number">1</span> - (<span class="number">0.314</span> * adjust))) + (rgba.b * (<span class="number">0.168</span> * adjust)));
    rgba.b = Math.min(<span class="number">255</span>, (rgba.r * (<span class="number">0.272</span> * adjust)) + (rgba.g * (<span class="number">0.534</span> * adjust)) + (rgba.b * (<span class="number">1</span>- (<span class="number">0.869</span> * adjust))));

    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <h2>Gamma</h2>
<p>Adjusts the gamma of the image.</p>
<h3>Arguments</h3>
<p>Range is from 0 to infinity, although sane values are from 0 to 4 or 5.
Values between 0 and 1 will lessen the contrast while values greater than 1 will increase it.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"gamma"</span>, (adjust) -&gt;
  <span class="property">@process</span> <span class="string">"gamma"</span>, (rgba) -&gt;
    rgba.r = Math.pow(rgba.r / <span class="number">255</span>, adjust) * <span class="number">255</span>
    rgba.g = Math.pow(rgba.g / <span class="number">255</span>, adjust) * <span class="number">255</span>
    rgba.b = Math.pow(rgba.b / <span class="number">255</span>, adjust) * <span class="number">255</span>
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              <h2>Noise</h2>
<p>Adds noise to the image on a scale from 1 - 100. However, the scale isn&#39;t constrained, so you 
can specify a value &gt; 100 if you want a LOT of noise.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"noise"</span>, (adjust) -&gt;
  adjust = Math.abs(adjust) * <span class="number">2.55</span>
  
  <span class="property">@process</span> <span class="string">"noise"</span>, (rgba) -&gt;
    rand = Calculate.randomRange adjust * -<span class="number">1</span>, adjust

    rgba.r += rand
    rgba.g += rand
    rgba.b += rand
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-18">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-18">&#182;</a>
              </div>
              <h2>Clip</h2>
<p>Clips a color to max values when it falls outside of the specified range.</p>
<h3>Arguments</h3>
<p>Supplied value should be between 0 and 100.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"clip"</span>, (adjust) -&gt;
  adjust = Math.abs(adjust) * <span class="number">2.55</span>

  <span class="property">@process</span> <span class="string">"clip"</span>, (rgba) -&gt;
    <span class="keyword">if</span> rgba.r &gt; <span class="number">255</span> - adjust
      rgba.r = <span class="number">255</span>
    <span class="keyword">else</span> <span class="keyword">if</span> rgba.r &lt; adjust
      rgba.r = <span class="number">0</span>

    <span class="keyword">if</span> rgba.g &gt; <span class="number">255</span> - adjust
      rgba.g = <span class="number">255</span>
    <span class="keyword">else</span> <span class="keyword">if</span> rgba.g &lt; adjust
      rgba.g = <span class="number">0</span>
      
    <span class="keyword">if</span> rgba.b &gt; <span class="number">255</span> - adjust
      rgba.b = <span class="number">255</span>
    <span class="keyword">else</span> <span class="keyword">if</span> rgba.b &lt; adjust
      rgba.b = <span class="number">0</span>

    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-19">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-19">&#182;</a>
              </div>
              <h2>Channels</h2>
<p>Lets you modify the intensity of any combination of red, green, or blue channels individually.</p>
<h3>Arguments</h3>
<p>Must be given at least one color channel to adjust in order to work.
Options format (must specify 1 - 3 colors):</p>
<pre>{
  red: 20,
  green: -5,
  blue: -40
}</pre>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"channels"</span>, (options) -&gt;
  <span class="keyword">return</span> @ <span class="keyword">if</span> <span class="keyword">typeof</span> options <span class="keyword">isnt</span> <span class="string">"object"</span>

  <span class="keyword">for</span> own chan, value <span class="keyword">of</span> options
    <span class="keyword">if</span> value <span class="keyword">is</span> <span class="number">0</span>
      <span class="keyword">delete</span> options[chan]
      <span class="keyword">continue</span>

    options[chan] /= <span class="number">100</span>

  <span class="keyword">return</span> @ <span class="keyword">if</span> options.length <span class="keyword">is</span> <span class="number">0</span>

  <span class="property">@process</span> <span class="string">"channels"</span>, (rgba) -&gt;
    <span class="keyword">if</span> options.red?
      <span class="keyword">if</span> options.red &gt; <span class="number">0</span>
        rgba.r += (<span class="number">255</span> - rgba.r) * options.red
      <span class="keyword">else</span>
        rgba.r -= rgba.r * Math.abs(options.red)

    <span class="keyword">if</span> options.green?
      <span class="keyword">if</span> options.green &gt; <span class="number">0</span>
        rgba.g += (<span class="number">255</span> - rgba.g) * options.green
      <span class="keyword">else</span>
        rgba.g -= rgba.g * Math.abs(options.green)

    <span class="keyword">if</span> options.blue?
      <span class="keyword">if</span> options.blue &gt; <span class="number">0</span>
        rgba.b += (<span class="number">255</span> - rgba.b) * options.blue
      <span class="keyword">else</span>
        rgba.b -= rgba.b * Math.abs(options.blue)

    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-20">&#182;</a>
              </div>
              <h2>Curves</h2>
<p>Curves implementation using Bezier curve equation. If you&#39;re familiar with the Curves 
functionality in Photoshop, this works in a very similar fashion.</p>
<h3>Arguments.</h3>
<pre>
  chan - [r, g, b, rgb]
  cps - [x, y]* (curve control points, min. 2; 0 - 255)
  algo - function (optional)
</pre>

<p>The first argument represents the channels you wish to modify with the filter. It can be an 
array of channels or a string (for a single channel). The rest of the arguments are 2-element 
arrays that represent point coordinates. They are specified in the same order as shown in this 
image to the right. The coordinates are in the range of 0 to 255 for both X and Y values.</p>
<p>It is possible to pass the function an optional function describing which curve algorithm to use.
It defaults to bezier.</p>
<p>The x-axis represents the input value for a single channel, while the y-axis represents the 
output value.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"curves"</span>, (chans, cps...) -&gt;
  last = cps[cps.length - <span class="number">1</span>]

  <span class="keyword">if</span> <span class="keyword">typeof</span> last <span class="keyword">is</span> <span class="string">"function"</span>
    algo = last
    cps.pop()
  <span class="keyword">else</span> <span class="keyword">if</span> <span class="keyword">typeof</span> last <span class="keyword">is</span> <span class="string">"string"</span>
    algo = Calculate[last]
    cps.pop()
  <span class="keyword">else</span>
    algo = Calculate.bezier</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-21">&#182;</a>
              </div>
              <p>If channels are in a string, split to an array</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  chans = chans.split(<span class="string">""</span>) <span class="keyword">if</span> <span class="keyword">typeof</span> chans <span class="keyword">is</span> <span class="string">"string"</span>
  chans = [<span class="string">'r'</span>, <span class="string">'g'</span>, <span class="string">'b'</span>] <span class="keyword">if</span> chans[<span class="number">0</span>] == <span class="string">"v"</span>

  <span class="keyword">if</span> cps.length &lt; <span class="number">2</span></pre></div></div>
            
        </li>
        
        
        <li id="section-22">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-22">&#182;</a>
              </div>
              <p>might want to give a warning now</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="keyword">throw</span> <span class="string">"Invalid number of arguments to curves filter"</span></pre></div></div>
            
        </li>
        
        
        <li id="section-23">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-23">&#182;</a>
              </div>
              <p>Generate a curve</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  bezier = algo cps, <span class="number">0</span>, <span class="number">255</span></pre></div></div>
            
        </li>
        
        
        <li id="section-24">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-24">&#182;</a>
              </div>
              <p>If the curve starts after x = 0, initialize it with a flat line
until the curve begins.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  start = cps[<span class="number">0</span>]
  bezier[i] = start[<span class="number">1</span>] <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>..start[<span class="number">0</span>]] <span class="keyword">if</span> start[<span class="number">0</span>] &gt; <span class="number">0</span></pre></div></div>
            
        </li>
        
        
        <li id="section-25">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-25">&#182;</a>
              </div>
              <p>... and the same with the end point</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  end = cps[cps.length - <span class="number">1</span>]
  bezier[i] = end[<span class="number">1</span>] <span class="keyword">for</span> i <span class="keyword">in</span> [end[<span class="number">0</span>].<span class="number">.255</span>] <span class="keyword">if</span> end[<span class="number">0</span>] &lt; <span class="number">255</span>

  <span class="property">@process</span> <span class="string">"curves"</span>, (rgba) -&gt;</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-26">&#182;</a>
              </div>
              <p>Now that we have the bezier curve, we do a basic hashmap lookup
to find and replace color values.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rgba[chans[i]] = bezier[rgba[chans[i]]] <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>..chans.length]
    rgba</pre></div></div>
            
        </li>
        
        
        <li id="section-27">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-27">&#182;</a>
              </div>
              <h2>Exposure</h2>
<p>Adjusts the exposure of the image by using the curves function.</p>
<h3>Arguments</h3>
<p>Range is -100 to 100. Values &lt; 0 will decrease exposure while values &gt; 0 will increase exposure.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>Filter.register <span class="string">"exposure"</span>, (adjust) -&gt;
  p = Math.abs(adjust) / <span class="number">100</span>

  ctrl1 = [<span class="number">0</span>, <span class="number">255</span> * p]
  ctrl2 = [<span class="number">255</span> - (<span class="number">255</span> * p), <span class="number">255</span>]

  <span class="keyword">if</span> adjust &lt; <span class="number">0</span>
    ctrl1 = ctrl1.reverse()
    ctrl2 = ctrl2.reverse()

  <span class="property">@curves</span> <span class="string">'rgb'</span>, [<span class="number">0</span>, <span class="number">0</span>], ctrl1, ctrl2, [<span class="number">255</span>, <span class="number">255</span>]</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
